/******************************************************************************
 * Copyright (C) 2013 ShenZhen ComTop Information Technology Co.,Ltd
 * All Rights Reserved.
 * 本软件为深圳康拓普开发研制。未经本公司正式书面同意，其他任何个人、团体不得使用、
 * 复制、修改或发布本软件.
 *****************************************************************************/

package com.code.common.util;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.code.common.exception.UtilException;

/**
 * Json工具类 
 * 
 * <pre>
 * 提供Json处理的工具方法
 * </pre>
 * 
 * @author 陈星凌
 * @since TOP4.0
 * @version 2013-1-29 陈星凌 新建
 */
public final class JsonUtil {
    
    /**
     * 日志对象
     */
    private final static Logger LOGGER = LoggerFactory.getLogger(JsonUtil.class);
    
    /**
     * 转换器
     */
    private static final ObjectMapper MAPPER;
    
    /**
     * 构造函数
     */
    private JsonUtil() {
    }
    
    static {
        MAPPER = new ObjectMapper();
        MAPPER.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        MAPPER.configure(JsonGenerator.Feature.QUOTE_FIELD_NAMES, false);
        MAPPER.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }
    
    /**
     * json格式字符串转list
     * 
     * @param <T> 转换对象类型
     * @param data 数据
     * @param clazz 类型
     * @return json格式字符串转list
     */
    public static <T> List<T> jsonToList(String data, Class<T> clazz)throws UtilException {
        List<T> lstResult = new ArrayList<T>(0);
        // 先转化为装有LinkedHashMap的List
        List<Object> lstObjs = jsonToObject(data, List.class);
        // 每个LinkedHashMap都转化为目标对象并装入结果集
        for (Iterator<Object> objIter = lstObjs.iterator(); objIter.hasNext();) {
            T objT = MAPPER.convertValue(objIter.next(), clazz);
            lstResult.add(objT);
        }
        return lstResult;
    }
    
    /**
     * lst格式字符串转json
     * 
     * @param lst 数据
     * @return json格式字符串
     * @see JsonUtil#objectToJson
     */
    public static String listToJson(List<? extends Object> lst) throws UtilException{
        return objectToJson(lst);
    }
    
    /**
     * JSON转对象
     * 
     * @param <T> 转换对象类型
     * @param json json字符串
     * @param t 转换对象类型
     * @return JSON转换的对象
     * @throws UtilException 
     */
    public static <T> T jsonToObject(String json, Class<T> t) throws UtilException {
        try {
            return MAPPER.readValue(json, t);
        } catch (JsonParseException e) {
            LOGGER.error("字符串：" + json + " 转化为对象" + t.getName() + " 异常", e);
            throw new UtilException("字符串：" + json + " 转化为对象" + t.getName() + " 异常", e);
        } catch (JsonMappingException e) {
            LOGGER.error("字符串：" + json + " 转化为对象" + t.getName() + " 异常", e);
            throw new UtilException("字符串：" + json + " 转化为对象" + t.getName() + " 异常", e);
        } catch (IOException e) {
            LOGGER.error("字符串：" + json + " 转化为对象" + t.getName() + " 异常", e);
            throw new UtilException("字符串：" + json + " 转化为对象" + t.getName() + " 异常", e);
        }
    }
    
    /**
     * JSON转对象
     * 
     * @param <T> 转换对象类型
     * @param json json字符串
     * @param t TypeReference
     * @return JSON转换的对象
     */
    public static <T> T jsonToObject(String json, TypeReference<T> t) throws UtilException{
        try {
            return (T) MAPPER.readValue(json, t);
        } catch (JsonParseException e) {
            LOGGER.error("字符串：" + json + " 转化为对象" + t.getType() + " 异常", e);
            throw new UtilException("字符串：" + json + " 转化为对象" + t.getType() + " 异常", e);
        } catch (JsonMappingException e) {
            LOGGER.error("字符串：" + json + " 转化为对象" + t.getType() + " 异常", e);
            throw new UtilException("字符串：" + json + " 转化为对象" + t.getType() + " 异常", e);
        } catch (IOException e) {
            LOGGER.error("字符串：" + json + " 转化为对象" + t.getType() + " 异常", e);
            throw new UtilException("字符串：" + json + " 转化为对象" + t.getType() + " 异常", e);
        }
    }
    
    /**
     * 对象转JSON
     * 
     * @param t 数据对象，可以是集合
     * @return json格式字符串
     */
    public static String objectToJson(Object t)throws UtilException {
        try {
            return MAPPER.writeValueAsString(t);
        } catch (JsonParseException e) {
            LOGGER.error(t.toString() + " 转化为对象JSON 异常", e);
            throw new UtilException(t.toString() + " 转化为对象JSON 异常", e);
        } catch (JsonMappingException e) {
            LOGGER.error(t.toString() + " 转化为对象JSON 异常", e);
            throw new UtilException(t.toString() + " 转化为对象JSON 异常", e);
        } catch (IOException e) {
            LOGGER.error(t.toString() + " 转化为对象JSON 异常", e);
            throw new UtilException(t.toString() + " 转化为对象JSON 异常", e);
        }
    }
    
    /**
     * 对象转JSON
     * 
     * @param t 数据对象，可以是集合
     * @param isQuote jason名是否加双引号
     * @return json格式字符串
     */
    public static String objectToJson(Object t, boolean isQuote)throws UtilException {
        try {
            if (isQuote) {
                MAPPER.configure(JsonGenerator.Feature.QUOTE_FIELD_NAMES, true);
            }
            return MAPPER.writeValueAsString(t);
        } catch (JsonParseException e) {
            LOGGER.error(t.toString() + " 转化为对象JSON 异常", e);
            throw new UtilException(t.toString() + " 转化为对象JSON 异常", e);
        } catch (JsonMappingException e) {
            LOGGER.error(t.toString() + " 转化为对象JSON 异常", e);
            throw new UtilException(t.toString() + " 转化为对象JSON 异常", e);
        } catch (IOException e) {
            LOGGER.error(t.toString() + " 转化为对象JSON 异常", e);
            throw new UtilException(t.toString() + " 转化为对象JSON 异常", e);
        }
    }

    /**
     * FIXME 方法注释信息(此标记自动完成,注释填写完成后请删除)
     * <pre>
     * 
     * </pre>
     * @return
     */
    public static Object getInstance() {
        // TODO 自动生成方法存根注释，方法实现时请删除此注释
        return null;
    }
}